package co.edu.usbcali.egrapico.logica;

import java.util.Vector;

/**
 * Clase para la traducci�n de la representaci�n de la
 * <Code>Parte L�gica
 * del Programa</Code> desde <I>GraPiCO Textual</I> hacia <I>C�lculo PiCO</I>.
 * <P> Recibe en <I>GraPiCO Textual</I> alguna de la siguientes opciones:<P> <Blockquote><Pre>
 *                   (Clonaci�n_1 Proceso_1 | ... | Clonaci�n_n Proceso_n)
 *                    Clonaci�n Proceso
 * </Pre></Blockquote> <P> Traducci�n a <I>C�lculo PiCO</I> seg�n el caso:<P> <Blockquote><Pre>
 *                   ParteL�gicaPrograma
 * </Pre></Blockquote> <P> En caso de existir condici�n de replicaci�n,
 * <Code>Clonaci�n</Code> en <I>GraPiCO Textual</I>:
 * <Code> * </Code> <P> Traducci�n de
 * <Code>Clonaci�n</Code> a <I>C�lculo PiCO</I>:
 * <Code> clone </Code>
 *
 * @author Johanna Noguera Le�n & Alejandro Berm�dez Mart�nez.
 * @version 1.0
 * @since Enero de 2005
 */
public class ProgramLogicalPart {

    // Variable para almacenar la parte l�gica del programa representada en c�lculo PiCO.
    String programLogicalPartPico = "";
    // Variable para almacenar el nombre del proceso, en el caso en que el programa
    // pertenece a otro proceso.
    String nameCurrentProcess = "";
    // Objeto de la clase Process.
    Process process;
    // Variable para almacenar una lista de procesos en GraPiCO Textual.
    Vector processList;
    // Variable para contar cuando empieza y termina un programa.
    int countProgram = 0;
    // Variable para almacenar la longitud de la parte l�gica del programa.
    int longExpression = 0;
    // Variable para almacenar donde empieza un proceso concurrente.
    int initProcess = 1;

    /**
     * M�todo constructor de la clase
     * <Code>ProgramLogicalPart</Code>.<P> Toma la
     * <Code>Parte L�gica del Programa</Code> en <I>GraPiCO Textual</I> y dado
     * que esta puede tener uno o m�s procesos, se identifica cual es el caso, y
     * se obtienen la(s) parejas Clonaci�n-Proceso en <I>GraPiCO Textual</I>.
     *
     * @param programLogicalPartGraPicoT Expresi�n equivalente a la
     * representaci�n de la
     * <Code>Parte L�gica del Programa</Code> en <I>GraPiCO Textual</I>.
     * @param nameProcess Nombre del proceso en traducci�n.
     */
    public ProgramLogicalPart(String programLogicalPartGraPicoT, String nameProcess) {

        // Obtiene el nombre del proceso que se est� traduciendo.
        nameCurrentProcess = nameProcess;

        // Inicializa vector de lista de procesos
        processList = new Vector();

        // Caso en el que hay mas de un proceso.
        if ((programLogicalPartGraPicoT.charAt(0) == '(' && programLogicalPartGraPicoT.charAt(1) == '*')
                || (programLogicalPartGraPicoT.charAt(0) == '(' && programLogicalPartGraPicoT.charAt(1) == '(')) {

            longExpression = programLogicalPartGraPicoT.length() - 1;
            /*
             * Se recorre la expresi�n en b�squeda del s�mbolo de sincronizaci�n
             * "pipe" el cual delimita los conjuntos Clonaci�n-Proceso. Se debe
             * tener en cuenta que el pipe encontrado no pertenezca a un
             * programa interno dentro del proceso.
             */
            for (int limit = 1; limit < longExpression; limit++) {
                if (programLogicalPartGraPicoT.charAt(limit) == '{') {
                    countProgram++;
                } else {
                    if (programLogicalPartGraPicoT.charAt(limit) == '}') {
                        countProgram--;
                    } else {
                        if ((programLogicalPartGraPicoT.charAt(limit) == '|') && (countProgram == 0)) {
                            processList.addElement(programLogicalPartGraPicoT.substring(initProcess, limit));
                            initProcess = limit + 1;
                        }
                    }
                }
            }
            processList.addElement(programLogicalPartGraPicoT.substring(initProcess, longExpression));
        } else {
            processList.addElement(programLogicalPartGraPicoT);
        }
    }

    /**
     * M�todo generador de la traducci�n del conjunto
     * <Code>Clonaci�n-Proceso</Code>. <P> Traduce el
     * <Code>Proceso</Code> concurrente que est� siendo evaluado en la
     * traducci�n de la
     * <Code>Parte L�gica del Programa</Code>.
     *
     * @return el proceso concurrente traducido a <I>C�lculo PiCO</I>.
     */
    public String traslateProcess(String concurrentProcess) {
        String clone = "";
        String proc = "";

        if (concurrentProcess.charAt(0) == '*') {
            proc = concurrentProcess.substring(1);
            clone = " clone ";
        } else {
            proc = concurrentProcess;
        }
        process = new Process(proc, nameCurrentProcess);
        proc = clone + process.traslate();

        return proc;
    }

    /**
     * M�todo generador de la traducci�n de la parte l�gica del programa. La
     * traducci�n de la parte l�gica del programa hacia <I>C�lculo PiCO</I> esta
     * formada por una pareja Clonaci�n-Proceso o por varias de estas, las
     * cuales deben estar entre par�ntesis y separadas por pipes.
     *
     * @return programLogicalPartPico. La parte l�gica de un programa traducida
     * a PiCO
     */
    public String traslate() {
        int size = processList.size();
        String cProcess = "";
        for (int count = 0; count < size; count++) {
            cProcess = (String) processList.get(count);
            if (count < size - 1) {
                programLogicalPartPico += traslateProcess(cProcess) + " | ";

            } else {
                programLogicalPartPico += traslateProcess(cProcess);
            }
        }
        if (size != 1) {
            programLogicalPartPico = " (" + programLogicalPartPico + ") ";
        }
        return programLogicalPartPico;
    }
}